package com.adam.masterSpringMVC4.controller;

import com.adam.masterSpringMVC4.profile.UserProfileSession;
import com.adam.masterSpringMVC4.tool.OkHttpUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.UrlResource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.util.*;

@Controller
public class LoginController {

    @Value("${login.oauth.github.clientId}")
    private String oauthGithubClientId;
    @Value("${login.oauth.github.clientSecret}")
    private String oauthGithubClientSecret;
    @Value("${login.oauth.github.access_token}")
    private String oauthGithubAccessTokenUrl;
    @Value("${login.oauth.github.user_info}")
    private String oauthGithubUserInfoUrl;

    @Autowired
    private UserProfileSession userProfileSession;

    @RequestMapping("/login")
    public String login(Model model) {
        model.addAttribute("oauthGithubClientId",oauthGithubClientId);
        model.addAttribute("oauthGithubClientSecret",oauthGithubClientSecret);
        return "loginPage";
    }

    @RequestMapping("/oauth/github/callback")
    public Object oauthGithubCallback(@RequestParam String code) throws IOException {
        System.out.println("oauth github code:" + code);
        if(code == null) {
            return null;
        }
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("client_id", oauthGithubClientId);
        paramMap.put("client_secret", oauthGithubClientSecret);
        paramMap.put("code", code);
        ObjectMapper objectMapper = new ObjectMapper();
        String paramJson = objectMapper.writeValueAsString(paramMap);
        String accessTokenJson = OkHttpUtil.doPostJson(oauthGithubAccessTokenUrl, paramJson);
        System.out.println("oauth github access token json:" + accessTokenJson);

        Map<String, String> accessTokenMap = objectMapper.readValue(accessTokenJson, new TypeReference<Map<String,String>>(){});
        String accessToken = accessTokenMap.get("access_token");
        String scope = accessTokenMap.get("scope");
        if(accessToken == null || scope == null)
            return null;
        List<String> scopes = Arrays.asList(scope.split(","));
        if(!scopes.contains("read:user"))
            return null;
        String userInfoJson = OkHttpUtil.doGetJsonWithToken(oauthGithubUserInfoUrl, accessToken);
        System.out.println("oauth github user info json:" + userInfoJson);

        Map<String,String> userInfoMap = objectMapper.readValue(userInfoJson, new TypeReference<Map<String,Object>>(){});
        userProfileSession.setLoginType(UserProfileSession.LoginType.Github);
        userProfileSession.setUserName(userInfoMap.get("login"));
        userProfileSession.setPicturePath(new UrlResource(userInfoMap.get("avatar_url")));
        userProfileSession.setEmail(userInfoMap.get("email"));
        List<GrantedAuthority> authorityList = new ArrayList<>();
        authorityList.add(new SimpleGrantedAuthority("ROLE_USER"));
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userInfoMap.get("login"), null, authorityList);
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        return "redirect:/profile";
    }

}
